/**
* \file Forme.cpp
* Ensemble des fonctions permettant la rotation et le déplacements des formes ainsi que l'accès aux formes et à leurs coordonnées
*/

#include<iostream>
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include"Forme.h"
#include"Constantes.h"
#include"Terrain.h"


/**
* Défini les pièces selon les 4 rotations
* le 1er indice correspond au nom de la forme defini dans constante.h,
* le 2eme indice correspond à l'orientation de la piece,
* le 3eme indice correspond à l'espace reserve pour la piece
*/

Case Piece[9][4][16] =
{
	///  BARRE
	{
		{ VIDE,VIDE,VIDE,VIDE,
		  BLEU,BLEU,BLEU,BLEU,
		  VIDE,VIDE,VIDE,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,BLEU,VIDE,VIDE,
		  VIDE,BLEU,VIDE,VIDE,
		  VIDE,BLEU,VIDE,VIDE,
		  VIDE,BLEU,VIDE,VIDE },
		{ VIDE,VIDE,VIDE,VIDE,
		  BLEU,BLEU,BLEU,BLEU,
		  VIDE,VIDE,VIDE,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,BLEU,VIDE,VIDE,
		  VIDE,BLEU,VIDE,VIDE,
		  VIDE,BLEU,VIDE,VIDE,
		  VIDE,BLEU,VIDE,VIDE }
	},
	/// L_NORMAL
	{
		{ VIDE,ROUGE,VIDE,VIDE,
		  VIDE,ROUGE,VIDE,VIDE,
		  VIDE,ROUGE,ROUGE,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,VIDE,VIDE,VIDE,
		  ROUGE,ROUGE,ROUGE,VIDE,
		  ROUGE,VIDE,VIDE,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,ROUGE,ROUGE,VIDE,
		  VIDE,VIDE,ROUGE,VIDE,
		  VIDE,VIDE,ROUGE,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,VIDE,ROUGE,VIDE,
		  ROUGE,ROUGE,ROUGE,VIDE,
		  VIDE,VIDE,VIDE,VIDE,
		  VIDE,VIDE,VIDE,VIDE }
	},
	/// L_INVERSE
	{
		{ VIDE,VIDE,JAUNE,VIDE,
		  VIDE,VIDE,JAUNE,VIDE,
		  VIDE,JAUNE,JAUNE,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ JAUNE,VIDE,VIDE,VIDE,
		  JAUNE,JAUNE,JAUNE,VIDE,
		  VIDE,VIDE,VIDE,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,JAUNE,JAUNE,VIDE,
		  VIDE,JAUNE,VIDE,VIDE,
		  VIDE,JAUNE,VIDE,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,VIDE,VIDE,VIDE,
		  JAUNE,JAUNE,JAUNE,VIDE,
		  VIDE,VIDE,JAUNE,VIDE,
		  VIDE,VIDE,VIDE,VIDE }
	},
	/// TRIANGLE
	{
		{ VIDE,VIDE,VIDE,VIDE,
		  VIDE,NOIR,VIDE,VIDE,
		  NOIR,NOIR,NOIR,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,NOIR,VIDE,VIDE,
		  VIDE,NOIR,NOIR,VIDE,
		  VIDE,NOIR,VIDE,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,VIDE,VIDE,VIDE,
		  NOIR,NOIR,NOIR,VIDE,
		  VIDE,NOIR,VIDE,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,NOIR,VIDE,VIDE,
		  NOIR,NOIR,VIDE,VIDE,
		  VIDE,NOIR,VIDE,VIDE,
		  VIDE,VIDE,VIDE,VIDE }
	},
	/// CARRE
	{
		{ VIDE,VIDE,VIDE,VIDE,
		  VIDE,MARRON,MARRON,VIDE,
		  VIDE,MARRON,MARRON,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,VIDE,VIDE,VIDE,
		  VIDE,MARRON,MARRON,VIDE,
		  VIDE,MARRON,MARRON,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,VIDE,VIDE,VIDE,
		  VIDE,MARRON,MARRON,VIDE,
		  VIDE,MARRON,MARRON,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,VIDE,VIDE,VIDE,
		  VIDE,MARRON,MARRON,VIDE,
		  VIDE,MARRON,MARRON,VIDE,
		  VIDE,VIDE,VIDE,VIDE }
    },
	/// ESCALIER
	{
		{ VIDE,VERT,VIDE,VIDE,
		  VIDE,VERT,VERT,VIDE,
		  VIDE,VIDE,VERT,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,VIDE,VIDE,VIDE,
		  VIDE,VERT,VERT,VIDE,
		  VERT,VERT,VIDE,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,VERT,VIDE,VIDE,
		  VIDE,VERT,VERT,VIDE,
		  VIDE,VIDE,VERT,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,VIDE,VIDE,VIDE,
		  VIDE,VERT,VERT,VIDE,
		  VERT,VERT,VIDE,VIDE,
		  VIDE,VIDE,VIDE,VIDE }
	},
	/// ESCALIER_INVERSE
	{
		{ VIDE,VIDE,ROSE,VIDE,
		  VIDE,ROSE,ROSE,VIDE,
		  VIDE,ROSE,VIDE,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,VIDE,VIDE,VIDE,
		  ROSE,ROSE,VIDE,VIDE,
		  VIDE,ROSE,ROSE,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,VIDE,ROSE,VIDE,
		  VIDE,ROSE,ROSE,VIDE,
		  VIDE,ROSE,VIDE,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,VIDE,VIDE,VIDE,
		  ROSE,ROSE,VIDE,VIDE,
		  VIDE,ROSE,ROSE,VIDE,
		  VIDE,VIDE,VIDE,VIDE }
	},

	/// PIECE8
	{
		{ VIOLET,VIOLET,VIDE,VIDE,
		  VIDE,VIOLET,VIDE,VIDE,
		  VIDE,VIOLET,VIOLET,VIDE,
		  VIDE,VIDE,VIOLET,VIDE },
		{ VIDE,VIDE,VIDE,VIOLET,
		  VIDE,VIOLET,VIOLET,VIOLET,
		  VIOLET,VIOLET,VIDE,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
		{ VIDE,VIOLET,VIDE,VIDE,
		  VIDE,VIOLET,VIOLET,VIDE,
		  VIDE,VIDE,VIOLET,VIDE,
		  VIDE,VIDE,VIOLET,VIOLET },
		{ VIDE,VIDE,VIDE,VIDE,
		  VIDE,VIDE,VIOLET,VIOLET,
		  VIOLET,VIOLET,VIOLET,VIDE,
		  VIOLET,VIDE,VIDE,VIDE }
	},

	/// CROIX
	{
        { VIDE,GRIS,VIDE,VIDE,
		  GRIS,GRIS,GRIS,VIDE,
		  VIDE,GRIS,VIDE,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
        { VIDE,GRIS,VIDE,VIDE,
		  GRIS,GRIS,GRIS,VIDE,
		  VIDE,GRIS,VIDE,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
        { VIDE,GRIS,VIDE,VIDE,
		  GRIS,GRIS,GRIS,VIDE,
		  VIDE,GRIS,VIDE,VIDE,
		  VIDE,VIDE,VIDE,VIDE },
        { VIDE,GRIS,VIDE,VIDE,
		  GRIS,GRIS,GRIS,VIDE,
		  VIDE,GRIS,VIDE,VIDE,
		  VIDE,VIDE,VIDE,VIDE }
	},
};


Case* FormeGetPiece(Forme f)
{
    assert(f.numforme >= 0);    /*! test si numforme et orientation peuvent être utilisés dans Piece */
    assert(f.numforme <= 8);
    assert(f.orientation >= 0);
    assert(f.orientation <= 3);
    return Piece[f.numforme][f.orientation];
}

void FormeInitialise(Forme *f, Terrain t)
{
    f->numforme = (StyleForme)((rand()/RAND_MAX)*8);
    f->orientation = (rand()/RAND_MAX)*3;
    f->positionXforme = (t.dimX/2)-2;
    f->positionYforme = 0;
}

void FormeAffichagePiece(Forme f)
{
    int i;
    for (i=1;i<=16;i++)
    {
        printf("%d",(FormeGetPiece(f))[i-1]);
        if (i%4==0)
        {
            printf("\n");
        }
    }
}

/**
* Deplace sur le terrain, la forme d'une case vers la droite
* \pre Le terrain doit être initialisé
* \param f et t permettent l'accès aux champs des structures Forme et Terrain
*/



/*
Jona : Lors du déplacement, ce qui me choque:
	- je ne vois pas où l'orientation de la piece est prise en compte
	- meme si le test de colision ne vérifie que pour les cases non vides, lors du déplacement ces dites casss ne sont pas ignorées ( écrasement ? ) 
*/

void FormeDeplacerDroite(Forme * f, Terrain *t)
{
    int i;
    int j;
    int k;
    if (FormeTestColision(*f, *t, f->positionXforme+1, f->positionYforme)== true)/*!test si le déplacement est possible */
    {
        for(i=4;i>0;i--) /*!on déplace la forme d'un cran vers la droite */
        {
            for (j=0; j<4; j++)
            {

                t->ter[f->positionXforme+i][f->positionYforme+j]=Piece[f->numforme][f->orientation][j*4+i-1]; /*on enlève 1 à i pour obtenir des nombres compris entre 0 et 15 */
            }
        }
        for(k=0; k<4; k++) /*!on vide la colonne de gauche */
        {
            t->ter[f->positionXforme][f->positionYforme+k] = VIDE;
        }
        f->positionXforme = f->positionXforme+1;
    }
}


void FormeDeplacerGauche(Forme *f, Terrain *t)
{
    int i;
    int j;
    int k;
    if (FormeTestColision(*f, *t, f->positionXforme-1, f->positionYforme)== true)/*!test si le déplacement est possible */
    {
        for(i=-1;i<3;i++)/*!on déplace la forme d'un cran vers la gauche */
        {
            for (j=0; j<4; j++)
            {
                t->ter[f->positionXforme+i][f->positionYforme+j]=Piece[f->numforme][f->orientation][j*4+i+1];
            }
        }
        for(k=0; k<4; k++)/*!on vide la colonne de droite */
        {
            t->ter[f->positionXforme+3][f->positionYforme+k] = VIDE;
        }
        f->positionXforme = f->positionXforme-1;
    }
}


void FormeDeplacerBas(Forme *f, Terrain *t)
{
    int i;
    int j;
    int k;
    if (FormeTestColision(*f, *t, f->positionXforme, f->positionYforme+1)== true)/*!test si le déplacement est possible */
    {
        for(j=4;j<0;j--)/*!on déplace la forme d'un cran vers le bas*/
        {
            for (i=0; i<4; i++)
            {
                t->ter[f->positionXforme+i][f->positionYforme+j]=Piece[f->numforme][f->orientation][(j-1)*4+i];
            }
        }
        for(k=0; k<4; k++)/*!on vide la ligne du haut */
        {
            t->ter[f->positionXforme+k][f->positionYforme] = VIDE;
        }
        f->positionYforme = f->positionYforme+1;
    }
}


bool FormeTestColision(Forme f,Terrain t,int x,int y)
{
    size_t i, j;
    for( i = 0 ; i < 4 ; i++ )
/*!on regarde sur terrain si l'emplacement dans lequel on veut mettre piece est vide aux endroits où piece ne l'est pas*/
      {
        for( j = 0 ; j < 4 ; j++ )
        {
            if(Piece[f.numforme][f.orientation][j*4+i] != VIDE)
                {
                   if(t.ter[x+i][y+j] != VIDE)
                   {
                       return false;
                   }
                }
        }
    }
    return true;
}
/* Jona : globalement ça m'a l'air bon, en tout cas la logique y est */

void FormePivoter(Forme f)
{
    f.orientation = f.orientation + 1;
}


int FormeGetPositionX(Forme f)
{
    return f.positionXforme;
}


int FormeGetPositionY(Forme f)
{
    return f.positionYforme;
}

/*void FormeNouvellePiece(Forme * pieceactuelle, Forme * piecesuivante)
{

}*/
